package org.example.common.fastdfs.service.impl;

import org.example.common.fastdfs.FileUploadBean;
import org.example.common.fastdfs.service.UploadFileService;
import org.example.common.fastdfs.config.FastDFSConfig;
import lombok.extern.slf4j.Slf4j;
import org.csource.common.NameValuePair;
import org.csource.common.MyException;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * FastDFS文件上传服务实现
 */
@Service
@Slf4j
public class UploadFileServiceImpl implements UploadFileService {

	@Autowired
	private FastDFSConfig fastDFSConfig;

	private volatile boolean clientInited = false;

	private void initClientIfNeeded() throws IOException, MyException {
		if (clientInited) return;
		synchronized (this) {
			if (clientInited) return;
			Properties properties = new Properties();
			properties.put("fastdfs.http_secret_key", fastDFSConfig.getSecretKey());
			properties.put("fastdfs.connect_timeout_in_seconds", String.valueOf(fastDFSConfig.getConnectTimeout()));
			properties.put("fastdfs.network_timeout_in_seconds", String.valueOf(fastDFSConfig.getNetworkTimeout()));
			properties.put("fastdfs.charset", fastDFSConfig.getCharset());
			properties.put("fastdfs.http_anti_steal_token", String.valueOf(fastDFSConfig.isAntiStealToken()));
			properties.put("fastdfs.http_tracker_http_port", String.valueOf(fastDFSConfig.getHttpPort()));
			properties.put("fastdfs.tracker_servers", String.join(",", fastDFSConfig.getTrackerList()));
			ClientGlobal.initByProperties(properties);
			clientInited = true;
			log.info("FastDFS客户端初始化完成: trackers={}", properties.getProperty("fastdfs.tracker_servers"));
		}
	}

	/**
	 * 文件上传
	 */
	@Override
	public FileUploadBean upload(String filename, InputStream is) throws IOException {
		TrackerServer trackerServer = null;
		StorageServer storageServer = null;
		try (InputStream in = is) {
			initClientIfNeeded();

			List<NameValuePair> metaList = new ArrayList<>();
			metaList.add(new NameValuePair("filename", filename));
			NameValuePair[] nvps = metaList.isEmpty() ? null : metaList.toArray(new NameValuePair[0]);

			String extname = StringUtils.getFilenameExtension(filename);
			if (extname == null) extname = "";

			byte[] fileBuff = readInputStream(in);

			TrackerClient trackerClient = new TrackerClient();
			trackerServer = trackerClient.getConnection();
			storageServer = trackerClient.getStoreStorage(trackerServer);
			StorageClient1 storageClient = new StorageClient1(trackerServer, storageServer);

			String uid;
			if (fastDFSConfig.getGroup() == null || fastDFSConfig.getGroup().trim().isEmpty()) {
				uid = storageClient.upload_file1(fileBuff, extname, nvps);
			} else {
				uid = storageClient.upload_file1(fastDFSConfig.getGroup(), fileBuff, extname, nvps);
			}

			if (uid == null) {
				throw new IOException("FastDFS返回文件ID为空");
			}

			FileUploadBean upload = new FileUploadBean();
			upload.setFilename(filename);
			upload.setExtname(extname);
			upload.setUid(uid);
			upload.setUrl(getURLByUid(uid));
			log.info("FastDFS上传成功: {} -> {}", filename, upload.getUrl());
			return upload;
		} catch (MyException e) {
			throw new IOException("FastDFS异常: " + e.getMessage(), e);
		} finally {
			closeQuietly(storageServer);
			closeQuietly(trackerServer);
		}
	}

	/** 关闭连接 */
	private void closeQuietly(StorageServer server) {
		if (server != null) {
			try { server.close(); } catch (Exception ignored) {}
		}
	}
	private void closeQuietly(TrackerServer server) {
		if (server != null) {
			try { server.close(); } catch (Exception ignored) {}
		}
	}

	/**
	 * 文件上传
	 */
	@Override
	public FileUploadBean upload(File file) throws IOException {
		if (file == null) {
			throw new IllegalArgumentException("文件为空");
		}
		if (!file.exists()) {
			throw new IllegalArgumentException("文件不存在");
		}
		if (!file.isFile()) {
			throw new IllegalArgumentException("不是文件，无法上传");
		}
		String filename = file.getName();
		try (InputStream fileIn = new FileInputStream(file)) {
			return upload(filename, fileIn);
		}
	}

	/**
	 * 根据文件ID获取URL
	 */
	@Override
	public String getUrlByFileID(String fileID) {
		return getURLByUid(fileID);
	}

	/**
	 * 上传的文件转化为字节数组
	 */
	private byte[] readInputStream(InputStream is) throws IOException {
		byte[] buffer = new byte[8192];
		int len;
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		while ((len = is.read(buffer)) != -1) {
			bos.write(buffer, 0, len);
		}
		return bos.toByteArray();
	}

	/**
	 * 拼接文件访问链接
	 */
	private String getURLByUid(String fileID) {
		if (fileID == null || fileID.trim().isEmpty()) {
			return null;
		}
		String base = fastDFSConfig.getWebServerUrl();
		if (base.endsWith("/")) {
			return base + fileID;
		} else {
			return base + "/" + fileID;
		}
	}
}
